package uk.co.q3c.deplan.server.util.useraccess;

import java.util.List;

import uk.co.q3c.deplan.server.util.rules.RuleManager;
import uk.co.q3c.deplan.server.util.useraccess.rules.UserAccessObjectRule;
import uk.co.q3c.deplan.server.util.useraccess.rules.UserAccessPropertyRule;
import uk.co.q3c.deplan.server.util.validation.rules.PropertyValuer;

/**
 * Provides rules for governing user access to objects using one of the states defined by {@link AccessLevel}. Rules applied at object level
 * apply to all properties, unless overridden by property rules. <br>
 * <br>
 * Thus an object may be defined as {@value AccessLevel#READ_ONLY}, but an individual property may be defined as
 * {@link AccessLevel#FULL_ACCESS} or {@link AccessLevel#HIDDEN}. The property rule always takes precedence regardless of the relative rank
 * of the access specified. <br>
 * <br>
 * Multiple rules may be provided. Whichever rule restricts access the most is taken as the prevailing rule
 * 
 * @author DSowerby 11 May 2009
 * 
 */
public class UserAccessController extends RuleManager<UserAccessPropertyRule, UserAccessObjectRule> {

	private static final long serialVersionUID = 1L;

	public enum AccessLevel {
		FULL_ACCESS, READ_ONLY, HIDDEN
	}

	public UserAccessController(PropertyValuer parent) {
		super(parent);
	}

	/**
	 * Returns the access level for the specified property. If there are multiple rules, the one with the strictest access level is
	 * returned.
	 * 
	 * @param propertyName
	 * @return
	 */
	public AccessLevel accessLevel(String propertyName) {
		AccessLevel accessLevel = AccessLevel.FULL_ACCESS;
		List<UserAccessPropertyRule> rules = propertyRules(propertyName);
		if (rules != null) {
			for (UserAccessPropertyRule rule : rules) {
				AccessLevel newAccessLevel = rule.accessLevel();
				if (accessLevel.compareTo(newAccessLevel) < 0) {
					accessLevel = newAccessLevel;
				}
			}
		}
		return accessLevel;
	}

}
